package com.mall.gateway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * 网关跨域配置
 */
@Configuration
public class CorsConfig {

    /**
     * CORS跨域配置
     */
    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        
        // 允许所有域名进行跨域调用
        config.setAllowedOriginPatterns(List.of("*"));
        
        // 允许所有请求头
        config.setAllowedHeaders(List.of("*"));
        
        // 允许所有请求方法
        config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD", "PATCH"));
        
        // 允许携带认证信息
        config.setAllowCredentials(true);
        
        // 暴露哪些头部信息（因为跨域访问默认不能获取全部头部信息）
        config.setExposedHeaders(List.of("*"));
        
        // 预检请求的有效期，单位为秒
        config.setMaxAge(3600L);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }

    /**
     * OPTIONS请求处理过滤器
     * 确保OPTIONS预检请求能够正确返回
     */
    @Bean
    public WebFilter corsOptionsFilter() {
        return new CorsOptionsWebFilter();
    }
    
    /**
     * CORS OPTIONS请求专用过滤器
     */
    private static class CorsOptionsWebFilter implements WebFilter, Ordered {
        
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
            ServerHttpRequest request = exchange.getRequest();
            
            if (request.getMethod() == HttpMethod.OPTIONS) {
                ServerHttpResponse response = exchange.getResponse();
                HttpHeaders headers = response.getHeaders();
                
                headers.add("Access-Control-Allow-Origin", "*");
                headers.add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
                headers.add("Access-Control-Allow-Headers", "*");
                headers.add("Access-Control-Allow-Credentials", "true");
                headers.add("Access-Control-Max-Age", "3600");
                
                response.setStatusCode(HttpStatus.OK);
                return response.setComplete();
            }
            
            return chain.filter(exchange);
        }
        
        @Override
        public int getOrder() {
            return -100; // 确保在认证过滤器之前执行
        }
    }
} 